From 6e602e052b8b2301379517ccfdca1ede6c9a9550 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 1 Jan 2020 20:47:19 -0500 Subject: [PATCH] text: Port to GtkDropTarget --- gtk/gtktext.c | 201 +++++++++++++++++++++++++------------------------- 1 file changed, 100 insertions(+), 101 deletions(-) diff --git a/gtk/gtktext.c b/gtk/gtktext.c index fd8a449399..de1f2ceb01 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -68,6 +68,7 @@ #include "gtknative.h" #include "gtkactionmuxerprivate.h" #include "gtkdragsource.h" +#include "gtkdragdest.h" #include "a11y/gtktextaccessible.h" @@ -332,19 +333,16 @@ static void gtk_text_state_flags_changed (GtkWidget *widget, GtkStateFlags previous_state); static void gtk_text_root (GtkWidget *widget); -static gboolean gtk_text_drag_drop (GtkWidget *widget, - GdkDrop *drop, +static gboolean gtk_text_drag_drop (GtkDropTarget *dest, int x, - int y); -static gboolean gtk_text_drag_motion (GtkWidget *widget, - GdkDrop *drop, + int y, + GtkText *text); +static gboolean gtk_text_drag_motion (GtkDropTarget *dest, int x, - int y); -static void gtk_text_drag_leave (GtkWidget *widget, - GdkDrop *drop); -static void gtk_text_drag_data_received (GtkWidget *widget, - GdkDrop *drop, - GtkSelectionData *selection_data); + int y, + GtkText *text); +static void gtk_text_drag_leave (GtkDropTarget *dest, + GtkText *text); /* GtkEditable method implementations @@ -726,10 +724,6 @@ gtk_text_class_init (GtkTextClass *class) widget_class->root = gtk_text_root; widget_class->mnemonic_activate = gtk_text_mnemonic_activate; widget_class->popup_menu = gtk_text_popup_menu; - widget_class->drag_drop = gtk_text_drag_drop; - widget_class->drag_motion = gtk_text_drag_motion; - widget_class->drag_leave = gtk_text_drag_leave; - widget_class->drag_data_received = gtk_text_drag_data_received; class->move_cursor = gtk_text_move_cursor; class->insert_at_cursor = gtk_text_insert_at_cursor; @@ -1710,6 +1704,8 @@ gtk_text_init (GtkText *self) GtkGesture *gesture; GtkEventController *controller; int i; + GtkDropTarget *dest; + GdkContentFormats *formats; gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN); @@ -1730,9 +1726,14 @@ gtk_text_init (GtkText *self) priv->selection_content = g_object_new (GTK_TYPE_TEXT_CONTENT, NULL); GTK_TEXT_CONTENT (priv->selection_content)->self = self; - gtk_drag_dest_set (GTK_WIDGET (self), 0, NULL, - GDK_ACTION_COPY | GDK_ACTION_MOVE); - gtk_drag_dest_add_text_targets (GTK_WIDGET (self)); + formats = gdk_content_formats_new (NULL, 0); + formats = gtk_content_formats_add_text_targets (formats); + dest = gtk_drop_target_new (0, formats, GDK_ACTION_COPY | GDK_ACTION_MOVE); + g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_text_drag_motion), self); + g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_text_drag_leave), self); + g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_drag_drop), self); + gdk_content_formats_unref (formats); + gtk_drop_target_attach (dest, GTK_WIDGET (self)); /* This object is completely private. No external entity can gain a reference * to it; so we create it here and destroy it in finalize(). @@ -6106,90 +6107,17 @@ gtk_text_selection_bubble_popup_set (GtkText *self) } static void -gtk_text_drag_leave (GtkWidget *widget, - GdkDrop *drop) +gtk_text_drag_leave (GtkDropTarget *dest, + GtkText *self) { - GtkText *self = GTK_TEXT (widget); GtkTextPrivate *priv = gtk_text_get_instance_private (self); + GtkWidget *widget = GTK_WIDGET (self); gtk_drag_unhighlight (widget); priv->dnd_position = -1; gtk_widget_queue_draw (widget); } -static gboolean -gtk_text_drag_drop (GtkWidget *widget, - GdkDrop *drop, - int x, - int y) -{ - GtkText *self = GTK_TEXT (widget); - GtkTextPrivate *priv = gtk_text_get_instance_private (self); - GdkAtom target = NULL; - - if (priv->editable) - target = gtk_drag_dest_find_target (widget, drop, NULL); - - if (target != NULL) - { - priv->drop_position = gtk_text_find_position (self, x + priv->scroll_offset); - gtk_drag_get_data (widget, drop, target); - } - else - gdk_drop_finish (drop, 0); - - return TRUE; -} - -static gboolean -gtk_text_drag_motion (GtkWidget *widget, - GdkDrop *drop, - int x, - int y) -{ - GtkText *self = GTK_TEXT (widget); - GtkTextPrivate *priv = gtk_text_get_instance_private (self); - GdkDragAction suggested_action; - int new_position, old_position; - - old_position = priv->dnd_position; - new_position = gtk_text_find_position (self, x + priv->scroll_offset); - - if (priv->editable && - gtk_drag_dest_find_target (widget, drop, NULL) != NULL) - { - suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE; - - if (priv->selection_bound == priv->current_pos || - new_position < priv->selection_bound || - new_position > priv->current_pos) - { - priv->dnd_position = new_position; - } - else - { - priv->dnd_position = -1; - } - } - else - { - /* Entry not editable, or no text */ - suggested_action = 0; - priv->dnd_position = -1; - } - - gdk_drop_status (drop, suggested_action); - if (suggested_action == 0) - gtk_drag_unhighlight (widget); - else - gtk_drag_highlight (widget); - - if (priv->dnd_position != old_position) - gtk_widget_queue_draw (widget); - - return TRUE; -} - static GdkDragAction gtk_text_get_action (GtkText *self, GdkDrop *drop) @@ -6218,19 +6146,20 @@ gtk_text_get_action (GtkText *self, } static void -gtk_text_drag_data_received (GtkWidget *widget, - GdkDrop *drop, - GtkSelectionData *selection_data) +got_text (GObject *source, + GAsyncResult *result, + gpointer data) { - GtkText *self = GTK_TEXT (widget); + GdkDrop *drop = GDK_DROP (source); + GtkText *self = GTK_TEXT (data); GtkTextPrivate *priv = gtk_text_get_instance_private (self); - GdkDragAction action; char *str; + GdkDragAction action; - str = (char *) gtk_selection_data_get_text (selection_data); + str = gdk_drop_read_text_finish (drop, result, NULL); action = gtk_text_get_action (self, drop); - if (action && str && priv->editable) + if (action && str) { int length = -1; int pos; @@ -6265,6 +6194,76 @@ gtk_text_drag_data_received (GtkWidget *widget, g_free (str); } +static gboolean +gtk_text_drag_drop (GtkDropTarget *dest, + int x, + int y, + GtkText *self) +{ + GtkTextPrivate *priv = gtk_text_get_instance_private (self); + GdkDrop *drop = gtk_drop_target_get_drop (dest); + + if (priv->editable && gdk_drop_has_value (drop, G_TYPE_STRING)) + { + priv->drop_position = gtk_text_find_position (self, x + priv->scroll_offset); + gdk_drop_read_text_async (drop, NULL, got_text, self); + } + else + gdk_drop_finish (drop, 0); + + return TRUE; +} + +static gboolean +gtk_text_drag_motion (GtkDropTarget *dest, + int x, + int y, + GtkText *self) +{ + GtkTextPrivate *priv = gtk_text_get_instance_private (self); + GdkDrop *drop = gtk_drop_target_get_drop (dest); + GtkWidget *widget = GTK_WIDGET (self); + GdkDragAction suggested_action; + int new_position, old_position; + + old_position = priv->dnd_position; + new_position = gtk_text_find_position (self, x + priv->scroll_offset); + + if (priv->editable && + gtk_drop_target_find_mimetype (dest) != NULL) + { + suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE; + + if (priv->selection_bound == priv->current_pos || + new_position < priv->selection_bound || + new_position > priv->current_pos) + { + priv->dnd_position = new_position; + } + else + { + priv->dnd_position = -1; + } + } + else + { + /* Entry not editable, or no text */ + suggested_action = 0; + priv->dnd_position = -1; + } + + gdk_drop_status (drop, suggested_action); + if (suggested_action == 0) + gtk_drag_unhighlight (widget); + else + gtk_drag_highlight (widget); + + if (priv->dnd_position != old_position) + gtk_widget_queue_draw (widget); + + return TRUE; +} + /* We display the cursor when * * - the selection is empty, AND -- 2.30.2